package A011thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 注意点：使用Lock功能同 synchronized
 */
public class A007_Thread_方法二_4个线程加一减一 {
    public static class Data2 {
        private int number = 0;

        private final Lock lock = new ReentrantLock();
        private final Condition condition = lock.newCondition();

        /**
         * 增量方法，number + 1
         */
        public void increment() {
            lock.lock();// 加锁
            try {
                while (number != 0) {
                    // 等待
                    condition.await();
                }
                // 开始具体的业务逻辑
                number++;
                System.out.println(Thread.currentThread().getName() + "=>" + number);
                // 加完后，通知其他线程 +1 操作完毕了
                condition.signalAll();// 唤醒全部等待线程
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();// 释放锁
            }
        }

        /**
         * 减量操作，number - 1
         */
        public void decrement() {
            lock.lock();// 加锁
            try {
                while (number == 0) {
                    // 等待
                    condition.await();
                }
                // 开始具体的业务逻辑
                number--;
                System.out.println(Thread.currentThread().getName() + "=>" + number);
                // 减完后，通知其他线程 -1 操作完毕了
                condition.signalAll();// 唤醒全部等待线程
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();// 释放锁
            }
        }
    }

    public static void main(String[] args) {
        Data2 data = new Data2();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.increment();
            }
        }, "A").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.decrement();
            }
        }, "B").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.increment();
            }
        }, "C").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.decrement();
            }
        }, "D").start();
    }
}
